/**

This file is part of MaCI/GIMnet.

MaCI/GIMnet is free software: you can redistribute it and/or modify it 
under the terms of the GNU Lesser General Public License as published 
by the Free Software Foundation, either version 3 of the License, or 
(at your option) any later version.

MaCI/GIMnet is distributed in the hope that it will be useful, but WITHOUT 
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 
FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public 
License for more details.

You should have received a copy of the GNU Lesser General Public 
License along with GIMnet. (See COPYING.LESSER) If not, see 
<http://www.gnu.org/licenses/>.

**/
/**
 * \file
 * \brief Simple mechanism for launching AP services together with the AP - implementation.
 * \author Antti Maula <antti.maula@tkk.fi>
 */
//*****************************************************************************
#include "servicelauncher.h"
#include "owndebug.h"
#include <stdlib.h>
#include <sys/types.h>
#include <signal.h>
#include <sys/wait.h>


//*****************************************************************************
//*****************************************************************************
//*****************************************************************************

pid_t servicelauncherLaunchService(const char *application, char *const* arguments)
{
  pid_t result = fork();

  if (result == -1) {
    dPrintLE(ODTEST,"fork() failed!");

  } else if (result == 0) {
    // Child
    // Execute!
    execvp(application, arguments);
    
    // Print error unconditionally.
    dPrintLE(ODERROR,"Failed to execute '%s'! Fatal error, child will exit.", 
             application);
    exit(1);

  } else {
    // Parent
    //    dPrint(ODTEST,"Parent continuing after creating a child with pid=%d", result);

  }

  return result;
}
//*****************************************************************************

int servicelauncherSignalService(const pid_t process, const int sig)
{
  int result = 0;

  result = kill(process, sig);

  return result;
}
//*****************************************************************************

int servicelauncherGetServiceStatus(const pid_t process)
{
  int result;
  int value;

  result = waitpid(process, &value, WNOHANG);
  /*  if (result < 0) {
    dPrintLE(ODINFO, "Failed to get status for PID=%d!", 
             process);
    
  } else if (result == process) {
    dPrint(3,"Succesfully Wait():ed for PID=%d, got result '%d'", 
           process, value);

  } else {
    dPrint(ODTEST,"Status not available for PID=%d", process);

    }*/
  
  // Returns: -1 on error, 0 no process still runnning, 1 on process exited
  return (result>1) ? 1 : result;
}
//*****************************************************************************

int servicelauncherWaitService(const pid_t process)
{
  int result;
  int value;
  
  result = waitpid(process, &value, 0);
  /*  if (result < 0) {
    dPrintLE(ODINFO, "Failed to get status for PID=%d!", 
             process);
    
  } else if (result == process) {
    dPrint(3,"Succesfully Wait():ed for PID=%d, got result '%d'", 
           process, value);
    
           }*/
  
  // Returns: -1 on error, 1 on process exited
  return (result>1) ? 1 : result;
}
//*****************************************************************************
//*****************************************************************************
#ifdef COMPILE_UNIT_TEST
/**
gcc -g3 -Wall -I. -I../utils -I./clientlib -DLINUX_OS -DUSE_SELECT_IO -DCOMPILE_UNIT_TEST servicelauncher.c ../utils/own*.c -lpthread -lrt -o servicelauncher.unit
 */
#include <stdio.h>
#include <assert.h>
#include <string.h>
#include "ownutils.h"
int main(int argc, char *argv[])
{
  debugInit();
  debugSetGlobalDebugLvl(ODINFO);
  char *app = "ls";
  char **param;
  int nparam = 0;

  if (argc > 1) app = argv[1];

  if (argc > 2) {
    nparam = argc - 2;
    int i;
    param = malloc(1024);
    memset(param, 0x00, 1024);
    param[0] = app;
    for(i=1; i<nparam+1; ++i) {
      param[i] = argv[1+i];
    }
  
  } else {
    nparam = 0;
    param = malloc(sizeof(char*));
    param[0] = NULL;

  }

  int x;
  for(x=0; x < nparam+2; ++x) {
    printf("%s\n", param[x]?param[x]:"NULL");
  }

  pid_t p = servicelauncherLaunchService(app, param);
  if (p > 0) {
    int r;
    printf("Succesfully executed '%s', got pid=%d\n", app, p);

    // Test status reading from active process
    r = servicelauncherGetServiceStatus(p);
    if (r == 0) {
      printf("Process %d running OK.\n", p);

    } else {
      printf("Process %d terminated or failed! (%s)\n", p, strerror(errno));

    }

    // Wait a while
    ownSleep_ms(5000);

    // Signal!
    r = servicelauncherSignalService(p, SIGTERM);
    if (!r) {
      printf("Process %d signaled succesfully with SIGTERM\n", p);

    } else {
      printf("Process %d signaling failed! (%s)\n", p, strerror(errno));

    }

    // Enter wait
    r = servicelauncherWaitService(p);
    if (r == 1) {
      printf("Successfully waited for process %d - terminated\n", p);

    } else {
      printf("Failed to wait for process %d! (%s)\n", p, strerror(errno));

    }
    
    

  }

  free(param);
  return 0;
}
#endif
//*****************************************************************************
//*****************************************************************************
//*****************************************************************************
//*****************************************************************************
//*****************************************************************************
//*****************************************************************************
//*****************************************************************************
//*****************************************************************************
